package se.kth.ict.id2203.sub;

import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import se.kth.ict.id2203.flp2p.FairLossPointToPointLink;
import se.kth.ict.id2203.flp2p.Flp2pSend;
import se.sics.kompics.ComponentDefinition;
import se.sics.kompics.Handler;
import se.sics.kompics.Negative;
import se.sics.kompics.Positive;
import se.sics.kompics.address.Address;
import se.sics.kompics.launch.Topology;

public class SUB extends ComponentDefinition {
	
	Negative<UnreliableBroadcast> sub = provides(UnreliableBroadcast.class);
	Positive<FairLossPointToPointLink> flp2p = requires(FairLossPointToPointLink.class);	

	private Address self;
	private Topology topology;
	private Set<Address> processSet;
	
	private static final Logger logger =
			LoggerFactory.getLogger(SUB.class);
	
	public SUB() {
		logger.info("SUB created.");
		subscribe(handleInit, control);
		subscribe(handleUnBroadcast, sub);
		subscribe(handleSUBMessage, flp2p);
	
	}
	
	Handler<SUBInit> handleInit = new Handler<SUBInit>() {
		public void handle(SUBInit event) {
			logger.info("SUB started.");
			topology = event.getTopology();
			self = topology.getSelfAddress();
			processSet = topology.getAllAddresses();
		}
	};
	
	Handler<UnBroadcast> handleUnBroadcast = new Handler<UnBroadcast>() {
		public void handle(UnBroadcast event) {
			
			String message = event.getMessage();
			long sn = event.getSn();
			for (Address process : processSet) {
				trigger(new Flp2pSend(process, new SUBMessage(self, message, sn)), flp2p);
				logger.info("Broadcast to " + process + " Message: " + message + " SN: " + sn);
			}
			
		}
	};
	
	Handler<SUBMessage> handleSUBMessage = new Handler<SUBMessage>() {
		public void handle(SUBMessage event) {
			
			String message = event.getMessage();
			long sn = event.getSn();
			Address pi = event.getSource();
			trigger(new UnDeliver(pi, message, sn), sub);
			
		}
	};
}
